/*
========================================================================
 Name        : SingaporeBusDocument.h
 Author      : 
 Copyright   : Your copyright notice
 Description : 
========================================================================
*/
#ifndef SINGAPOREBUSDOCUMENT_H
#define SINGAPOREBUSDOCUMENT_H

#include <akndoc.h>

#include "IapConnectionManager.h"
#include "googlepositioning.h"
#include "positionrequest.h"
#include "CActiveHelper.h"
#include "asyncfileloader.h"
#include "singaporebusstructures.h"
#include "singaporebusparsers.h"
#include "FunTrace.h"
#include <http\RHTTPTransaction.h>
#include <http\RHTTPSession.h>
#include <http\RHTTPHeaders.h>
#include <http\MHTTPTransactionCallback.h>
#include <apgcli.h>
#include <eikprogi.h>
#include <AknProgressDialog.h>
#include <AknWaitDialog.h>
#include "ApplicationUpdater.h"
#include "SmrtQuery.h"
#include "IrisQuery.h"
#include "TflQuery.h"
#include "PublictransportsgQuery.h"
#include "e32hashtab.h"
#include "Iterator.h"
#include "How2GoQuery.h"
#include "SingaporeBusDrawItemsSG.h"
#include "SingaporeBusDrawItemsLD.h"
#include "JourneyPlanner.h"
#include "TFLJourneyPlannerQuery.h"
#include "AdQuery.h"
#include "WorkerThread.h"
#include "ActiveTarget.h"
#include "MapTileServer.h"

#ifndef __SERIES60_3X__
#include <sensrvchannel.h>
#include <sensrvchannelinfo.h>
#include <sensrvtypes.h>
#include <sensrvchannelfinder.h>
#include <sensrvdatalistener.h>
#include <sensrvmagneticnorthsensor.h>
#include <sensrvmagnetometersensor.h>
#include <sensrvpropertylistener.h>
#endif


class CEikAppUi;


#define APPLICATION_VERSION "2.3.3"

struct CCalibrationDialog;

/**
* @class	CSingaporeBusDocument SingaporeBusDocument.h
* @brief	A CAknDocument-derived class is required by the S60 application 
*           framework. It is responsible for creating the AppUi object. 
*/
class CSingaporeBusDocument : public CAknDocument, public MIapConnectionManagerCallback, public MPositionRequestCallback, public MGooglePositionRequestCallback, public MAsyncFileLoaderCallback, public MApplicationUpdaterCallback, public MActiveHelperCallback<RTimer*>, public MActiveHelperCallback<RConnection*>

#ifndef __SERIES60_3X__
, public MSensrvDataListener, public MSensrvPropertyListener
#endif

	{
public: 
	// constructor
	static CSingaporeBusDocument* NewL( CEikApplication& aApp );

	RFile iLogFile;
	CIapConnectionManager* iConnectionManager;
	CGooglePositionRequest* iGooglePositionRequest;
	CPositionRequest* iPositionRequest, * iNetworkPositionRequest;
	enum { KShowAll, KShowFavorites } iBusStopsListShowMode;
	TTime iTimeInBackground;
	TBool iPositionTracking;
	TBool iUseLocation;
	TBool iAskUseLocation;
	
	TBool iDisplayCalibrationMessage;
	CCalibrationDialog* iCalibrationDialog;
	void CalibrationDialogCallback(CCalibrationDialog* aDialog, TInt aButtonId, CArrayFixFlat<TInt>* aIndexArray);
	void DisplayCalibrationMessageL();
	void CalibrationAnimationMessageCallbackL();
	scalp::CActiveTarget* iCalibrationMessageTimerTarget;
	scalp::CActiveTarget* iCalibrationMessageAnimationTimerTarget;
	TTime iCalibrationAnimationMessageStart;
	RTimer iCalibrationMessageTimer;
	RTimer iCalibrationMessageAnimationTimer;

#ifndef __SERIES60_3X__
	// Calibration: http://library.developer.nokia.com/index.jsp?topic=/S60_5th_Edition_Cpp_Developers_Library/GUID-CADD234E-B2D2-4E28-B420-5A2B0322C890.html
	LManagedPtr<CSensrvChannel> iMagnetometerSensor;
	LManagedPtr<CSensrvChannel> iMagneticNorthSensor;
    TSensrvMagneticNorthData iMagneticNorthData;
    TInt iMagnetometerCalibrationLevel;
    TInt iDataReceived_PrevMagnetometerCalibrationLevel;
    TInt iMagneticNorthDataError;
    void PropertyChanged( CSensrvChannel& aChannel, const TSensrvProperty& aChangedProperty );
    void PropertyError( CSensrvChannel& aChannel, TSensrvErrorSeverity aError );
    void SetPropertySuccessIndicationChanged(TSetPropertySuccessIndicator aIndication );
	void GetPropertyListenerInterfaceL( TUid aInterfaceUid, TAny*& aInterface );
	void DataReceived(CSensrvChannel& aChannel, TInt aCount, TInt aDataLost);
	void DataError(CSensrvChannel& aChannel, TSensrvErrorSeverity aError);
	void GetDataListenerInterfaceL(TUid aInterfaceUid, TAny*& aInterface);
	RTimer iCompassTimer;
	TTime iTimeStartRefreshCompass;
	scalp::CActiveTarget* iCompassTimerTarget;
	TInt iCompassTimerInterval;
	void StopCompassTrackingL();
	void RefreshCompass();
#endif

	LManagedPtr<CWorkerThread> iWorkerThread;
	void InitWorkerThread();
	void UninitWorkerThread();
	
	void HandleForegroundEventL(TBool aForeground);
	
	RArray<TCoordinate> iPrevGPSPositions;
	TCoordinate iPosition;
	TBuf<KPositionMaxModuleName> iPositionModuleName;
	TReal32 iPositionAccuracy;
	TTime iPositionTime;
	TPositionModuleInfo::TTechnologyType iPositioningTechnology;
	enum TPositioningStatus { PS_NOT_AVAILABLE, PS_ERROR, PS_PENDING, PS_FOUND } iPositioningStatus;
	TInt iPositionError;
	TInt iPendingPositionRequests;
	
	TBuf<128> iPositionDescriptionBuf;
	TPtrC PositionDescription();
	
	void CreateFavoritePaneL(const TDesC& aPaneName);
	void DeleteFavoritePaneL(TInt aPaneId);
	void RenameFavoritePaneL(TInt aPaneId, const TDesC& aPaneName);

	
	LManagedPtr< CIterator<const TStation*> > iStationUnderlying;
	TReal32 StationOrderItem(const TStation* aStation);
	LManagedPtr< COrderingIterator<const TStation*, TReal32> > iStationOrderIterator;
	RHashMap< TBuf8<15>, const TStation* >* iServicesStationMap;

	friend class CSingaporeBusStopsListBox;
	friend class CSingaporeBusStopsListBoxView;
	friend class CSingaporeBusServicesListBoxView;
	friend class CSingaporeBusRouteListBox;
	friend class CSingaporeBusRouteListBoxView;
	friend class CSingaporeBusRouteView;

private:
	RArray<HBufC8*> iDisplayServiceKeys;
	TInt iCurrentDisplayServiceKey;
	
	TBool iDisplayRouteSteps;
	
	const TStation* iSelectedStation;
	const TService* iSelectedService;
	
	
	
	

public:
	
	TInt iTravelOption;
	const TStation* iOriginStation;
	const TStation* iDestinationStation;
	
	RArray<TPtrC8> iFavoriteStations;
	RArray<HBufC8*> iStationsLoaded;
	
	LManagedPtr<CSingaporeBusDrawItemsSG> iSingaporeBusDrawItemsSG;
	LManagedPtr<CSingaporeBusDrawItemsLD> iSingaporeBusDrawItemsLD;

	RArray< RHashSet< TBuf8<15> >* > iFavorites;
	RArray<HBufC*> iFavoritesTitles;
	TInt iCurrentFavorite;
	
	TBool iScheduleRequestManual;
	TInt iCachedTilesCount;
	
	CAsyncFileLoader* iStationsFileLoader;
	CAsyncFileLoader* iServicesFileLoader;
	CAsyncFileLoader* iServicesPathsFileLoader;
	CAsyncFileLoader* iServicesPathsIndexFileLoader;
	
	void PowerDownL();
	
	TInt SelectFavoritePaneL();
	
		
	RFs iFsData, iFsLogs, iFsResource;
	
	TBool LoadCurrentDisplayServiceL();
	TBool LoadServicePathL(const TDesC8& aServiceKey);
	
	void MAsyncFileLoaderCallbackRunL(CAsyncFileLoader* aSource, TInt aStatus, RBuf8& aBuf);
	
	
	TInt LoadSettingsL(TUint& aVersion);
	TInt SaveSettingsL();
	
	RFileLogger iFileLogger;
	void EnableLogs();
	void DisableLogs();
	
	RArray<TUint32> iIapPriorityList;
	TTime iEvaluateStartTime;

	
	RBuf8 iStationsBuf;
	RBuf8 iServicesBuf;
	RBuf8 iServicesPathsIndexBuf;
	RBuf8 iServicesPathsBuf;
	
	RArray<TStation> iStations;
	RArray<const TStation*> iStationsSortedByStationNumber;
	static TInt TLinearOrder_Station(const TStation* const& left, const TStation* const& right);
	RArray<TPtrC8> iStationServiceKeys;
	RArray<TPtrC8> iServiceStations;
	RArray<TService> iServices;
	RArray<const TService*> iServicesSortedByServiceKey;
	static TInt TLinearOrder_Service(const TService* const& left, const TService* const& right);
	RArray<TIndexItem> iServicesPathsIndex;
	RArray<TServicePath> iServicePaths;
	RArray<TCoordinate> iServicePathsCoordinates;
	RArray<const TIndexItem*> iServicesPathsIndexSortedByKey;
	
	~CSingaporeBusDocument();
	
	LManagedPtr< CAsyncCallBack > iInitLocationServicesAsyncCallback;
	TInt InitLocationServices();
	void RefreshPosition();
	
		
	void MIapConnectionManagerCallbackRunL(TInt iStage, TInt iError);
	void MGooglePositionRequestCallbackRunL(TInt aStatus, TInt aLastError, const TCoordinate& aCoordinate, TReal32 aAccuracy);
	void MPositionRequestCallbackRunL(CPositionRequest* aPositionRequest, const TRequestStatus& aStatus, const TPositionInfo& aPositionInfo);

	TBool iApplicationUpdaterWaitingConnection;
	TInt iAutoCheckForUpdatePeriod; // in days
	TInt iCountAutoCheckForUpdateInSession; // how many times we checked for update in this session
	TFileName iInstallationFile;
	TTime iLastAutoCheckForUpdate;
	CApplicationUpdater* iApplicationUpdater;
	void MApplicationUpdaterCallbackRunL(const TApplicationUpdaterEvent& aEvent);
	
    TVwsViewId iPrevViewId, iPrevPrevViewId;
	
	TBool iGooglePositionRequestWaitingConnection;
	TBool iGpsAvailable;
	RTimer iGpsGraceTimer;
	TInt iGpsGraceTime; // in s
	CActiveHelper<RTimer*>* iGpsGraceTimerHelper;
	void MActiveHelperCallbackRunL(CActiveHelper<RTimer*>* aActiveHelper, RTimer* aTimer);
	TInt MActiveHelperCallbackRunError(CActiveHelper<RTimer*>* aActiveHelper, RTimer* aTimer, TInt aError);
	void MActiveHelperCallbackDoCancel(CActiveHelper<RTimer*>* aActiveHelper, RTimer* aTimer);
		
	CActiveHelper<RConnection*>* iIsConnectionActiveHelper;
	TPckg<TBool> iConnectionActive;
	void MActiveHelperCallbackRunL(CActiveHelper<RConnection*>* aActiveHelper, RConnection* aConnection);
	TInt MActiveHelperCallbackRunError(CActiveHelper<RConnection*>* aActiveHelper, RConnection* aConnection, TInt aError);
	void MActiveHelperCallbackDoCancel(CActiveHelper<RConnection*>* aActiveHelper, RConnection* aConnection);
	
	
	
	
	void InitConnectionManagerL();
	void ConnectL();
	
	LManagedPtr< CSmrtSession > iSmrtSession;
	LManagedPtr< CIrisSession > iIrisSession;
	LManagedPtr< CTflSession > iTflSession;
	LManagedPtr<CHow2GoQuery> iHow2GoQuery;
	LManagedPtr<CAdSession> iAdSession;
	LManagedPtr<CTFLJourneyPlannerQuery> iTflJourneyPlannerQuery;
	LManagedPtr<CMapTileServer> iMapTileServer;
	
	TTime iTimeLastAd;
	
	void How2GoQueryAnswerL(CHow2GoQuery*, TInt aLastError, TInt aStatusCode, CJourneyPlannerOutput* aOutput);
	void TflJourneyPlannerQueryAnswerL(CTFLJourneyPlannerQuery*, TInt, TInt, CJourneyPlannerOutput*);

	
	TInt iJourneyPlannerError, iJourneyPlannerStatusCode;
	LManagedPtr<CJourneyPlannerOutput> iJourneyPlannerOutput;
	
	void SetOriginL(const TStation* aStation);
	void SetDestinationL(const TStation* aStation);
	void SubmitJourneyPlannerQueryL();
	void RefreshRouteL();
	void ToggleFavoriteL(const TDesC8& aStrFavorite, TInt aFavoriteGroup);
	void StoreFavoriteL(TDes8& aBuf, const TService* aService) const;
	void StoreFavoriteL(TDes8& aBuf, const TStation* aStation) const;
	void StoreFavoriteL(TDes8& aBuf, const TStation* aStation, const TService* aService) const;

	TInt FindFavorite(const TDes8& aBuf) const;
	TInt FindFavorite(const TService* aService) const;
	TInt FindFavorite(const TStation* aStation) const;
	TInt FindFavorite(const TStation* aStation, const TService* aService) const;
	
private: 
	// constructors
	CSingaporeBusDocument( CEikApplication& aApp );
	void ConstructL();
	void TriggerNotifyPositionChange();
	void TriggerNotifyFileLoaded(const CAsyncFileLoader* aFileLoader);
	void TriggerNotifyConnected();
	void TriggerNotifyAzimuthChanged();
	
public: 
	// from base class CEikDocument
	CEikAppUi* CreateAppUiL();
	};
#endif // SINGAPOREBUSDOCUMENT_H
